#include <iostream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <unistd.h>

#define PATHNAME "/tmp"
#define PROJ_ID 0x66

const int gsize = 128;

class Shm
{
public:
    Shm() : _shmid(-1), _size(gsize),_start_addr(nullptr)
    {
    }
    void Create()
    {
        GetHelper(IPC_CREAT|IPC_EXCL|0666);
    }
    void Get()
    {
        GetHelper(IPC_CREAT);
    }
    void Attch()
    {
        _start_addr = shmat(_shmid,nullptr,0);
        if(_start_addr == (void*)-1)
        {
            exit(4);
        }
    }

    void Detach()
    {
        int n = shmdt(_start_addr);
        (void)n;
    }
    void Delete()
    {
        int n = shmctl(_shmid, IPC_RMID, NULL);
        if (n < 0)
        {
            std::cerr << "shmctl fail";
            exit(3);
        }
    }
    void* Addr()
    {
        return _start_addr;
    }
    int Size()
    {
        return _size;
    }

    ~Shm()
    {
    }

private:
    key_t GetKey()
    {
        return ftok(PATHNAME, PROJ_ID);
    }
    void GetHelper(int mode)
    {
        key_t k = GetKey();
        if (k < 0)
        {
            std::cerr << "ftok error";
            exit(2);
        }
        _shmid = shmget(k, _size, mode);
        if (_shmid < 0)
        {
            std::cerr << "shmget creat fail..." << std::endl;
            exit(1);
        }
    }

private:
    int _size;
    int _shmid;
    void* _start_addr;
};
